﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NasuTek.Shion.Agent;
using System.Threading;
using System.IO;
using Skybound.Gecko;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
using NasuTek.Shion.Extencibility;
using System.Resources;
using System.Text.RegularExpressions;
using WeifenLuo.WinFormsUI.Docking;

namespace NasuTek.Shion
{
    public partial class Form1 : Form
    {
        public static Dictionary<string, Dictionary<string, string[]>> ChannelText = new Dictionary<string, Dictionary<string, string[]>>();
        public static Dictionary<string, Dictionary<string, string>> Topics = new Dictionary<string, Dictionary<string, string>>();
        public static Dictionary<string, Dictionary<string, string>> ChannelModes = new Dictionary<string, Dictionary<string, string>>();
        public static Dictionary<string, Dictionary<string, string[]>> NamesList = new Dictionary<string, Dictionary<string, string[]>>();
        public static Dictionary<string, IrcClient> Clients = new Dictionary<string, IrcClient>();
        public static Dictionary<string, Dictionary<string, List<string>>> Ops = new Dictionary<string, Dictionary<string, List<string>>>();
        public static Dictionary<string, Dictionary<string, List<string>>> HalfOps = new Dictionary<string, Dictionary<string, List<string>>>();
        public static Dictionary<string, Dictionary<string, List<string>>> Vops = new Dictionary<string, Dictionary<string, List<string>>>();
        public static List<string> Raw = new List<string>();
        public static ExtencibilityManager em = new ExtencibilityManager(Clients);

        public static List<string> DebuggingServers = new List<string>();
        bool exiting;
        bool debugging;
        public GeckoWebBrowser webBrowser1 = new GeckoWebBrowser();
        static public Configuration config;

        public static string activeChannelMode;

        bool openingInspector = false;
        bool opening = true;
        public Form1()
        {
            InitializeComponent();
            em.ToolsAddinsMenu = addinsToolStripMenuItem;
            em.Panel = panel;
            if (Program.debug == false) Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp"));
            else Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp-debug"));
            webBrowser1.Dock = DockStyle.Fill;
            webBrowser1.CreateWindow += new GeckoCreateWindowEventHandler(webBrowser1_CreateWindow);
            HTMLClientArea.Controls.Add(webBrowser1);
            GetConfig();
            em.NickListView = NickList;
            NickList.ContextMenuStrip = em.NickMenu;
        }

        void webBrowser1_CreateWindow(object sender, GeckoCreateWindowEventArgs e)
        {
            MessageBox.Show(e.WebBrowser.Url.AbsoluteUri);
            Process.Start(e.WebBrowser.Url.ToString());
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (opening == false)
            {
                if ((e.Node.SelectedImageKey == "Console") || (e.Node.SelectedImageKey == "Channel") || (e.Node.SelectedImageKey == "Query"))
                {
                    SetActiveWindow(e.Node.Parent.Text, e.Node.Text.ToLower());
                    e.Node.ForeColor = Color.Black;
                }
                if (e.Node.SelectedImageKey == "Debug")
                {
                    SetActiveWindow("Debug", "Debug");
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CreateLayout();
            opening = false;
            SetToPDialog();
            new Splash().ShowDialog();

            GetConfig();

            em.Themes.Add("Default Theme", new Theme());

            if (Directory.Exists(Path.Combine(Application.StartupPath, "Plugins")))
            {
                foreach (string i in Directory.GetFiles(Path.Combine(Application.StartupPath, "Plugins"), "*.dll"))
                {
                    try
                    {
                        em.RegisterNewPlugin(i);
                    }
                    catch (Exception ex)
                    {
                        if (ex.Message != "could not invoke method")
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }
                }
            }

            foreach (KeyValuePair<string,Theme> i in em.Themes)
            {
                ToolStripMenuItem Theme = new ToolStripMenuItem(i.Key);
                Theme.Click += new EventHandler(Theme_Click);
                changeThemeToolStripMenuItem.DropDown.Items.Add(Theme);
            }

            foreach (Server i in config.Servers)
            {
                CreateServer(i.Address, i.Nick, i.UserName, i.Name, i.NickServPassword, i.OperUserName, i.OperPassword, false);
                foreach (string x in i.Channels)
                {
                    JoinChannel(i.Address, x, false);
                }
            }
        }

        void Theme_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem m = (ToolStripMenuItem)sender;
            config.Theme = m.Text;
            RefreshWindow();
        }

        private void toolStripSplitButton2_ButtonClick(object sender, EventArgs e)
        {

        }

        private void deleteChannelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ServerExplorer.SelectedNode.Text.StartsWith("#"))
            {
                Clients[ServerExplorer.SelectedNode.Parent.Text].RfcPart(ServerExplorer.SelectedNode.Text);
                if (MessageBox.Show("Do you want to remove this channel from autojoin?", "Shion 6", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) config.GetServer(ServerExplorer.SelectedNode.Parent.Text).RemoveChannel(ServerExplorer.SelectedNode.Text.ToLower());
                Ops[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text.ToLower());
                HalfOps[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text.ToLower());
                Vops[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text.ToLower());
                NamesList[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text.ToLower());
                ChannelText[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text.ToLower());
                webBrowser1.Navigate("about:blank");
                ServerExplorer.SelectedNode.Remove();
                SaveConfig();
            }
            else if (ServerExplorer.SelectedNode.SelectedImageKey == "Query")
            {
                ChannelText[ServerExplorer.SelectedNode.Parent.Text].Remove(ServerExplorer.SelectedNode.Text);
                ServerExplorer.SelectedNode.Remove();
                webBrowser1.Navigate("about:blank");
            }
        }

        private void addChannelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddChannel ac = new AddChannel();
            foreach (KeyValuePair<string, Dictionary<string, string[]>> i in ChannelText)
            {
                ac.comboBox1.Items.Add(i.Key);
            }
            if (ac.ShowDialog() == DialogResult.OK)
            {
                if (ac.comboBox1.Text != "")
                {
                    if (ac.textBox1.Text != "")
                    {
                        if (ac.textBox1.Text.StartsWith("#"))
                        {
                            if (ServerExplorer.Nodes[ac.comboBox1.Text].Nodes.ContainsKey(ac.textBox1.Text) == false)
                            {
                                JoinChannel(ac.comboBox1.Text, ac.textBox1.Text, ac.checkBox1.Checked);
                            }
                        }
                        else
                        {
                            if (ServerExplorer.Nodes[ac.comboBox1.Text].Nodes.ContainsKey(ac.textBox1.Text) == false)
                            {
                                ChannelText[ac.comboBox1.Text].Add(ac.textBox1.Text.ToLower(), new string[] { });
                                ServerExplorer.Nodes[ac.comboBox1.Text].Nodes.Add(ac.textBox1.Text.ToLower(), ac.textBox1.Text.ToLower(), "Query", "Query");
                                SetActiveWindow(ac.comboBox1.Text, ac.textBox1.Text);
                            }
                        }
                    }
                }
            }
        }

        private void addServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddServer ads = new AddServer();
            if (ads.ShowDialog() == DialogResult.OK)
            {
                CreateServer(ads.textBox1.Text, ads.textBox2.Text, ads.textBox4.Text, ads.textBox3.Text, ads.textBox5.Text, ads.textBox7.Text, ads.textBox6.Text, ads.checkBox1.Checked);
            }
            
        }

        private void deleteServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ServerExplorer.SelectedNode.Parent == null)
            {
                if(MessageBox.Show("Do you want to remove thic server from autojoin?", "Shion 6", MessageBoxButtons.YesNo, MessageBoxIcon.Question)== DialogResult.Yes)                config.RemoveServer(ServerExplorer.SelectedNode.Text);
                Ops.Remove(ServerExplorer.SelectedNode.Text);
                HalfOps.Remove(ServerExplorer.SelectedNode.Text);
                Vops.Remove(ServerExplorer.SelectedNode.Text);
                NamesList.Remove(ServerExplorer.SelectedNode.Text);
                ChannelText.Remove(ServerExplorer.SelectedNode.Text);
                Clients[ServerExplorer.SelectedNode.Text].RfcQuit();
                SaveConfig();
            }
            else
            {
                if (MessageBox.Show("Do you want to remove thic server from autojoin?", "Shion 6", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) config.RemoveServer(ServerExplorer.SelectedNode.Parent.Text);
                Ops.Remove(ServerExplorer.SelectedNode.Parent.Text);
                HalfOps.Remove(ServerExplorer.SelectedNode.Parent.Text);
                Vops.Remove(ServerExplorer.SelectedNode.Parent.Text);
                NamesList.Remove(ServerExplorer.SelectedNode.Parent.Text);
                ChannelText.Remove(ServerExplorer.SelectedNode.Parent.Text);
                Clients[ServerExplorer.SelectedNode.Parent.Text].RfcQuit();
                SaveConfig();
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Program.debug == false) Directory.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp"), true);
            else Directory.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp-debug"), true);
            exiting = true;
            V();
            SaveConfig();
        }

        private void aboutNasuTelkToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new About(config.Name, config.Hash).ShowDialog();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {

        }

        private void toolStripButton1_Click_1(object sender, EventArgs e)
        {
            
        }

        private void editServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ServerExplorer.SelectedNode.Parent == null)
            {
                AddServer ads = new AddServer();
                ads.textBox1.Text = config.GetServer(ServerExplorer.SelectedNode.Text).Address;
                ads.textBox2.Text = config.GetServer(ServerExplorer.SelectedNode.Text).Nick;
                ads.textBox3.Text = config.GetServer(ServerExplorer.SelectedNode.Text).Name;
                ads.textBox4.Text = config.GetServer(ServerExplorer.SelectedNode.Text).UserName;
                ads.textBox5.Text = config.GetServer(ServerExplorer.SelectedNode.Text).NickServPassword;
                if (ads.ShowDialog() == DialogResult.OK)
                {
                    config.GetServer(ServerExplorer.SelectedNode.Text).Address = ads.textBox1.Text;
                    config.GetServer(ServerExplorer.SelectedNode.Text).Nick = ads.textBox2.Text;
                    config.GetServer(ServerExplorer.SelectedNode.Text).Name = ads.textBox3.Text;
                    config.GetServer(ServerExplorer.SelectedNode.Text).UserName = ads.textBox4.Text;
                    config.GetServer(ServerExplorer.SelectedNode.Text).NickServPassword = ads.textBox5.Text;
                    MessageBox.Show("Changes will change on next restart.", "Shion", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            new Debugger(this).Show();
        }

        private void modifyConfigurationFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new ConfigEditor().ShowDialog();
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            
        }

        private void insertColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendBar.Text += "";
            SendBar.SelectionStart = SendBar.Text.Length;
        }

        private void insertBoldToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendBar.Text += "";
            SendBar.SelectionStart = SendBar.Text.Length;
        }

        private void SetToPDialog()
        {
            SetActiveWindow("", "");
            if (Program.debug == false)
            {
                Properties.Resources.Shion.Save(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp\\Shion.png"));
                File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp\\ShionTempHTML.html"), Properties.Resources.Shion1);
                webBrowser1.Navigate(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp\\ShionTempHTML.html"));
            }
            else
            {
                Properties.Resources.Shion.Save(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp-debug\\Shion.png"));
                File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp-debug\\ShionTempHTML.html"), Properties.Resources.Shion1);
                webBrowser1.Navigate(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ShionTemp-debug\\ShionTempHTML.html"));
            }
        }

        private void pluginManagerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new PluginManager().ShowDialog();
        }

        private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            ListViewItem i = (ListViewItem)e.Item;
            SendBar.Text += i.Text;
        }

        private void completeNickToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string[] o = SendBar.Text.Split(' ');
                string NickBeginning = o[o.GetUpperBound(0)];
                o[o.GetUpperBound(0)] = NickList.FindItemWithText(NickBeginning).Text;
                SendBar.Text = String.Join(" ", o);
                SendBar.SelectionStart = SendBar.Text.Length;
            }
            catch (NullReferenceException) { }
        }

        private void helpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new HelpWindow().ShowDialog();
        }

        private void activateShion6ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new setup().ShowDialog();
        }

        private void updateShion6ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start("Updator.exe");
        }

        private void comboBox1_Click(object sender, EventArgs e)
        {
            AcceptButton = button1;
        }

        private void textBox2_Click(object sender, EventArgs e)
        {
            AcceptButton = button2;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Clients[em.activeServer].RfcTopic(em.activeChannel, Topic.Text);
        }

        private void t(object sender, EventArgs e)
        {

        }

        private void inspectorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                toolStripStatusLabel1.Text = "Opening Inspector... Please Wait...";
                openingInspector = true;
                Clients[em.activeServer].RfcMode(em.activeChannel);
            }
            catch (KeyNotFoundException) { }
        }

        private void rawLogToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void debuggerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new Debugger(this).ShowDialog();
        }

        private void tabPage2_Click(object sender, EventArgs e)
        {

        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void standardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (standardToolStripMenuItem.Checked) { standardToolStripMenuItem.Checked = false; }
            else { standardToolStripMenuItem.Checked = true; }
            toolStrip1.Visible = standardToolStripMenuItem.Checked;
        }

        private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void channelBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DockContent serverBrowser = new DockContent();
            ServerExplorer.Dock = DockStyle.Fill;
            serverBrowser.Controls.Add(ServerExplorer);
            serverBrowser.Text = "Server Explorer";
            serverBrowser.Show(panel, DockState.DockLeft);
        }

        private void nickBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DockContent nickBrowser = new DockContent();
            NickList.Dock = DockStyle.Fill;
            nickBrowser.Controls.Add(NickList);
            nickBrowser.Text = "Nick Browser";
            nickBrowser.Show(panel, DockState.DockRight);
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            openingInspector = true;
            Clients[em.activeServer].RfcMode(em.activeChannel);
        }

        private void toolStripButton2_Click_1(object sender, EventArgs e)
        {
            new Debugger(this).Show(panel);
        }

        private void toolStripContainer1_TopToolStripPanel_Click(object sender, EventArgs e)
        {

        }

        public void CreateLayout()
        {
            DockContent serverBrowser = new DockContent();
            ServerExplorer.Dock = DockStyle.Fill;
            serverBrowser.Controls.Add(ServerExplorer);
            serverBrowser.Text = "Server Explorer";
            serverBrowser.Show(panel, DockState.DockLeft);
            serverBrowser.CloseButtonVisible = false;

            DockContent nickBrowser = new DockContent();
            NickList.Dock = DockStyle.Fill;
            nickBrowser.Controls.Add(NickList);
            nickBrowser.Text = "Nick Browser";
            nickBrowser.Show(panel, DockState.DockRight);
            nickBrowser.CloseButtonVisible = false;
            O_O clientWindow = new O_O();
            ClientWindow.Dock = DockStyle.Fill;
            clientWindow.Controls.Add(ClientWindow);
            clientWindow.Text = "Communication";
            clientWindow.CloseButton = false;
            clientWindow.DockAreas = DockAreas.Document;
            clientWindow.Show(panel);
        }

        private void toolStripButton1_Click_2(object sender, EventArgs e)
        {
            new PluginManager().Show(panel);
        }

        private void ClientWindow_Paint(object sender, PaintEventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (em.activeServer != "")
            {
                toolStripStatusLabel4.Text = String.Format("{0}:{1}:{2}:{3}", new object[] { Clients[em.activeServer].Lag.Hours, Clients[em.activeServer].Lag.Minutes, Clients[em.activeServer].Lag.Seconds, Clients[em.activeServer].Lag.Milliseconds });
            }
        }
    }

    public class O_O : DockContent
    {
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Tab)
            {
                try
                {
                    string[] o = Program.Form1Data.SendBar.Text.Split(' ');
                    string NickBeginning = o[o.GetUpperBound(0)];
                    o[o.GetUpperBound(0)] = Program.Form1Data.NickList.FindItemWithText(NickBeginning).Text;
                    Program.Form1Data.SendBar.Text = String.Join(" ", o);
                    Program.Form1Data.SendBar.SelectionStart = Program.Form1Data.SendBar.Text.Length;
                    return true;
                }
                catch (NullReferenceException) { return true; }
            }
            else
            {
                return base.ProcessDialogKey(keyData);
            }
        }
    }
}